package quirk;

import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.Method;

public class QueryGrammar {
  private String query;
  
  public QueryGrammar(String query) {
    this.query = query;
  }
  
  /**
   * Validates the grammar of the query used to construct this object.
   * Stops validating and returns false on the first rule found to be broken
   * @return true if the query is grammatically correct
   */
  public boolean isValid() {
    boolean grammarIsValid = true;
    
    Class cls = this.getClass();
    Method[] methods = cls.getDeclaredMethods();
    for(int m = 0; m < methods.length && grammarIsValid; m++) {
      if(methods[m].getName().startsWith("rule")) {
        try {
          Boolean ruleValue = (Boolean)methods[m].invoke(this, null);
          grammarIsValid = ruleValue.booleanValue();          
        }
        catch(Exception ex) {
          //if you figure out how this could happen, then handle it accordingly
        }
      }
    }
    return grammarIsValid;
  }
  
  /**
   * Checks if all opened term lists are closed
   * @return false if there are incomplete term lists
   */
  private boolean ruleCompleteTermlists() throws IOException {
    StringReader reader = new StringReader(query);
    int openTermlists = 0;
    for (int nextChar = reader.read(); nextChar != Constants.EOF; nextChar = reader.read()) {
      if (nextChar == '(')
        openTermlists++;
      else if (nextChar == ')') 
        openTermlists--;
    }
    
    return openTermlists == 0;
  }
  
  /**
   * Checks if the query is empty
   * @return false if the query is empty, true otherwise
   */
  private boolean ruleQueryNotEmpty() {
    String test = query.replaceAll("[()|]", "").trim();
    return test.length() > 0;
  }
  
  /**
   * @return true if all OR operators are used legally
   */
  private boolean ruleCorrectOrOperators() throws IOException {
    boolean rule = true;
    if(query.startsWith("|") || query.endsWith("|"))
      rule = false;
    else {
      String test = query.replaceAll(" ", "");
      StringReader reader = new StringReader(test);
      for(int ch = reader.read(); ch != Constants.EOF; ch = reader.read()) {
        if(ch == '|') {
          int nextChar = Util.peek(reader);
          if(nextChar == '|' || nextChar == ')') {
            rule = false;
            break;
          } 
        }
      }
    }    
    return rule;
  }
  
  /** Tests if the character is part of the grammar used to form queries */
  public static boolean isGrammar(int ch) {
    return ch == '(' || ch == ')' || ch == '|' || ch == ' ';    
  }
  
  /** Main method is just for testing */
  public static void main(String args[]) {
    String test = "( foo  || bar  ))";
    QueryGrammar grammar = new QueryGrammar(test);
    System.out.println("test1: "+grammar.isValid());
  }
}
